package com.xexun.gpstracker.service;

import java.util.*;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.*;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.xexun.gpstracker.AppContext;
import com.xexun.gpstracker.baby.activity.ChatActivity;
import com.xexun.gpstracker.channel.R;
import com.xexun.gpstracker.common.Constants;
import com.xexun.gpstracker.pojo.Device;
import com.xexun.gpstracker.util.CommUtil;
import com.xexun.gpstracker.util.Utils;
import com.xexun.gpstracker.vo.CmdType;
import com.xexun.gpstracker.vo.Session;

/**
 *
 */
public class BlueToothAntiLostService extends Service {
    private static final String TAG = BlueToothAntiLostService.class.getName();

    private final Object lock = new Object();
    private NotificationManager mNotifyMgr;
    private NotificationCompat.Builder builder;

    private BluetoothAdapter mBluetoothAdapter;
    private String mAddress;
    private Boolean scanFinished = true;
    private Set<String> bles = new HashSet<>();
    private long bleStartTime = 0;
    private int bleConnectFailedTime = 0;
    private Timer bleTimer;
    private TimerTask scanTask;
    private MediaPlayer mediaPlayer;
    private boolean firstFind = true;
    private boolean bleIsOn = false;

    private Context mContext;
    private String imei;


    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "蓝牙服务开启了...");
        mContext = this;

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        bleIsOn = mBluetoothAdapter.isEnabled();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "蓝牙服务关闭了...");
        try {
            mContext.unregisterReceiver(bleBroadcastReceiver);
        } catch (Exception e) {
            //
        }
        cleanBleAlert();

        if (!bleIsOn && mBluetoothAdapter != null) {
            mBluetoothAdapter.disable();
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int res = super.onStartCommand(intent, flags, startId);
        if (intent == null) {
            return res;
        }
        boolean optOpen = intent.getBooleanExtra("OPEN", false);
        if (optOpen) {
            imei = intent.getStringExtra("IMEI");
            openBluetoothAntiLost();
            initNotification();
        } else {
            closeBluetoothAntiLost();
        }
        return res;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void openBluetoothAntiLost() {
        if (CommUtil.isBlank(imei)) {
            return;
        }
        Device device = Session.getInstance().getDevice(imei);
        if (device == null) {
            return;
        }
        mAddress = device.getMac();
        if (!mBluetoothAdapter.isEnabled()) {
            mBluetoothAdapter.enable();
        }
        mContext.registerReceiver(bleBroadcastReceiver, bleIntentFilter());
        bleTimer = bleTimer == null ? new Timer() : bleTimer;
        bleStartTime = System.currentTimeMillis();
        firstFind = true;
        scanTask = new BLEScanTask(0);
        bleTimer.schedule(scanTask, 0, Constants.BLE_SCAN_PERIOD);
    }

    private void closeBluetoothAntiLost() {
        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.cancelDiscovery();
        }
        scanFinished = true;
        if (bleTimer != null) {
            bleTimer.cancel();
            bleTimer.purge();
            bleTimer = null;
        }
        bleConnectFailedTime = 0;

        try {
            mContext.unregisterReceiver(bleBroadcastReceiver);
        } catch (Exception e) {
            //
        }

        cleanBleAlert();

        String key = CmdType.BL.getType() + "_" + imei;
        Utils.getPreferences(mContext).edit().putBoolean(key, false).apply();
    }

    private final BroadcastReceiver bleBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                synchronized (lock) {
                    scanFinished = true;
                }
            } else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                bles.add(device.getAddress());
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                Log.d(TAG, device.getName() + "蓝牙连接已断开！！");
                mBluetoothAdapter.cancelDiscovery();
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //一个搜索周期结束
                Log.d(TAG, "一个搜索周期结束,扫描到的设备：" + bles);
                synchronized (lock) {
                    scanFinished = true;
                }
                boolean find = false;
                for (String mac : bles) {
                    if (mAddress.equalsIgnoreCase(mac)) {
                        find = true;
                    }
                }
                long curr = System.currentTimeMillis();
                if (!find && curr - bleStartTime < Constants.BLE_PRESCAN_PERIOD) {
                    Log.d(TAG, "在开启蓝牙时未搜到设备");
                } else if (!find && firstFind && curr - bleStartTime > Constants.BLE_PRESCAN_PERIOD) {
                    Utils.sendCommand(imei, null, getString(R.string.bluetooth_beyond_time), null);
                    closeBluetoothAntiLost();
                } else if (!find) {
                    Log.d(TAG, "未找到设备，3秒后再试");
                    bleConnectFailedTime++;
                    if (bleConnectFailedTime < Constants.BLE_FAILED_RETRY_TIME && bleTimer != null) {
                        bleTimer.schedule(new BLEScanTask(0), Constants.BLE_FAILED_SCAN_PERIOD);
                    }
                } else {
                    Log.d(TAG, "找到设备：" + mAddress);
                    if (firstFind) {
                        firstFind = false;
                        Utils.sendCommand(imei, null, getString(R.string.bluetooth_connected), null);
                    }
                    bleConnectFailedTime = 0;
                    bleStartTime = 0;
                }
                if (bleConnectFailedTime >= Constants.BLE_FAILED_RETRY_TIME) {
                    //Alert
                    Log.d(TAG, "开始报警");
                    closeBluetoothAntiLost();
                    Utils.sendCommand(imei, null, getString(R.string.bluetooth_connect_lost), null);
                    bleAlert();
                }
            }
        }

    };

    private void bleAlert() {
        mNotifyMgr.notify("ble", R.drawable.ic_launcher, builder.build());

        DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                cleanBleAlert();
            }
        };

        Device device = Session.getInstance().getDevice(imei);
        String babyName = (device == null || CommUtil.isBlank(device.getName())) ? getString(R.string.baby) : device.getName();
        Map<String, Object> map = new HashMap<>();
        map.put("listener", listener);
        map.put("cont", getString(R.string.bluetooth_connect_lost) + getString(R.string.ble_baby_leave, babyName));
        AppContext.getEventBus().post(map, Constants.EVENT_TAG_BLEANTILOSTNOTE);

        mediaPlayer = MediaPlayer.create(mContext, R.raw.alarm);
        mediaPlayer.setVolume(1.0f, 1.0f);
        mediaPlayer.setLooping(true);
        mediaPlayer.start();

        SharedPreferences sp = Utils.getPreferences(mContext);
        Utils.Vibrate(mContext, new long[]{1000, 2000, 1000, 2000}, true, sp.getBoolean(Constants.MSG_VIBRATE, true));//震动2秒停1秒
    }

    private void cleanBleAlert() {
        if (mNotifyMgr != null) {
            mNotifyMgr.cancelAll();
        }
        if (null != mediaPlayer) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }
        Utils.closeVibrate(mContext);
    }

    private static IntentFilter bleIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); //开关状态
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND); //发现设备
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); //设备已连接
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED); //正在断开蓝牙
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //蓝牙已断开
        intentFilter.addAction(Constants.CONNECT_BLE);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        return intentFilter;
    }

    private void initNotification() {
        // 创建NotificationManager对象
        mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        // 创建一个即将要执行的PendingIntent对象
        if (builder == null) {
            builder = new NotificationCompat.Builder(this);
        }
        Intent intent = new Intent(mContext, ChatActivity.class);
        intent.putExtra("chat", Session.getInstance().getMapEntityByImei(imei));
        intent.putExtra("addOn", true);
        intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        PendingIntent pdIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);

        Device device = Session.getInstance().getDevice(imei);
        String babyName = (device == null || CommUtil.isBlank(device.getName())) ? getString(R.string.baby) : device.getName();
        builder.setSmallIcon(R.drawable.ic_launcher).setContentTitle(getString(R.string.ble_disconnect))
                .setContentText(getString(R.string.ble_baby_leave, babyName)).setAutoCancel(true).setContentIntent(pdIntent).setLights(0xffff0000, 1000, 2000);
    }

    private class BLEScanTask extends TimerTask {
        private long delay;

        public BLEScanTask(long delay) {
            this.delay = delay;
        }

        @Override
        public void run() {
            try {
                synchronized (lock) {
                    if (!scanFinished) {
                        return;
                    }
                    scanFinished = false;
                }
                if (delay > 0) {
                    wait(delay);
                }
                bles.clear();
                mBluetoothAdapter.startDiscovery();
            } catch (Exception e) {
                //
            }
        }
    }
}
